package org.pz.camunda.controller;

import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricActivityInstance;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.task.Task;
import org.pz.camunda.dto.CamundaTaskDto;
import org.pz.camunda.dto.CamundaTaskNodeDto;
import org.pz.camunda.enums.OperateTypeEnum;
import org.pz.camunda.mapper.VariablesMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 任务相关
 * */
@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private VariablesMapper variablesMapper;

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 查询任务
     * @param user 流程流转到 user 的任务
     * */
    @RequestMapping("/list/{user}")
    public List<CamundaTaskDto> queryTaskList(@PathVariable String user) {
        List<Task> list = taskService.createTaskQuery()
                //camunda 默认不会获取 form-key,需要显式调用一下，否则 getForm 会抛异常
                .initializeFormKeys()
//                .taskAssignee(user)
                .taskCandidateUser(user)
                .orderByTaskCreateTime().desc()
                .list();
        return list.stream().map(CamundaTaskDto::new).collect(Collectors.toList());
    }

    /**
     * 获取当前任务的所有变量
     * */
    @RequestMapping("/{taskId}/variables")
    public Map<String, Object> getTaskVariables(@PathVariable String taskId) {
        return taskService.getVariables(taskId);
    }

    /**
     * 获取当前任务的某个变量
     * */
    @RequestMapping("/{taskId}/variables/{variableName}")
    public Object queryMsgByInstanceId(@PathVariable String taskId, @PathVariable String variableName) {
        return taskService.getVariable(taskId, variableName);
    }

    /**
     * 获取任务信息
     * */
    @RequestMapping("/processDefinition/{taskId}")
    public Map<String, Object> processDefinition(@PathVariable String taskId) {

        //返回结果 Map
        Map<String,Object> resultMap = new HashMap<>();

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(ObjectUtils.isEmpty(task)){
            throw new RuntimeException("未获取到相关流程: " + taskId);
        }

        //流程实例开始时间
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        resultMap.put( "startTime",dateFormat.format(historicProcessInstance.getStartTime()));
        resultMap.put("instanceId",task.getProcessInstanceId());

        //流程走过的人工节点，todo 这里后续替换成自己的吧
        List<HistoricActivityInstance> userTasks = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceStartTime().asc().list();
        Map<String, HistoricActivityInstance> hisMap = userTasks.stream().collect(Collectors.toMap(HistoricActivityInstance::getTaskId, e -> e, (o, o2) -> o));
        List<CamundaTaskNodeDto> nodes = variablesMapper.nodeList(hisMap.keySet());

        nodes.forEach(camundaTaskNodeDto -> {
            camundaTaskNodeDto.setNodeName(hisMap.get(camundaTaskNodeDto.getTaskId()).getActivityName());
            camundaTaskNodeDto.setOperateName(OperateTypeEnum.getName(camundaTaskNodeDto.getOperateType()));
        });
        resultMap.put("nodes", nodes);

        //流程定义名称
        ActivityInstance instance = runtimeService.getActivityInstance(task.getProcessInstanceId());
        resultMap.put("processName", instance.getActivityName());

        //流程变量
        resultMap.put("variables", taskService.getVariables(taskId));

        return resultMap;
    }

}
